#include "MemoryPool.h"

#include <memory>

namespace MemoryPool
{
MemoryPool::MemoryPool(size_t blockSize)
    : _blockSize(blockSize)
    , _slotSize(0)
    , _firstBlock(nullptr)
    , _curSlot(nullptr)
    , _freeList(nullptr)
    , _lastSlot(nullptr)
{

}

MemoryPool::~MemoryPool()
{
    //把连续的block删除
    Slot *cur = _firstBlock;
    while (cur != nullptr)
    {
        Slot *next = cur->next;
        operator delete(reinterpret_cast<void*>(cur));
        cur = next;
    }
}

void MemoryPool::init(size_t size)
{
    assert(size > 0);
    _slotSize = size;
    _firstBlock = nullptr;
    _curSlot = nullptr;
    _freeList = nullptr;
    _lastSlot = nullptr;

}

void *MemoryPool::allocate()
{
    Slot *slot = popFreeList();
    Slot *temp;
    if (slot != nullptr)
    {
        return slot;
    }
    else
    {
        std::lock_guard<std::mutex> lock(_mutexForBlock);
        if (_curSlot >= _lastSlot)
        {
            //当前的内存块没有可用的内存槽了，需要开辟新的内存
            allocateNewBlock();
        }
        temp = _curSlot;
        _curSlot += _slotSize/sizeof(Slot);

    }
    return temp;
}

void MemoryPool::deallocate(void *ptr)
{
    if (!ptr)
    {
        return;
    }
    Slot *slot = reinterpret_cast<Slot*>(ptr);
    pushFreeList(slot);
}

void MemoryPool::allocateNewBlock()
{
    //采用头插法
    void* newBlock = operator new(_blockSize);//申请一块blocksize大小的内存块
    reinterpret_cast<Slot*>(newBlock)->next = _firstBlock;
    _firstBlock = reinterpret_cast<Slot*>(newBlock);

    char *body = reinterpret_cast<char*>(newBlock) + sizeof(Slot);
    size_t paddingSize = padPointer(body,_slotSize);
    _curSlot = reinterpret_cast<Slot*>(body+paddingSize);

    _lastSlot = reinterpret_cast<Slot*>(reinterpret_cast<size_t>(newBlock)+_blockSize - _slotSize +1);
}

size_t MemoryPool::padPointer(char* p, size_t align)
{
    return align - (reinterpret_cast<size_t>(p) % align);
}




}
